#include "CgProgram.h"
#include <iostream>
#include <QDebug>

CgProgram::CgProgram(char* vpFilename /* = 0 */, char* vpEntryPoint /* = 0 */, char* fpFileName /* = 0 */, char* fpEntryPoint /* = 0 */,
					 char* gpFileName /* = 0 */, char* gpEntryPont /* = 0*/)
{
	m_FragmentProgram = NULL;
	m_VertexProgram = NULL;
	m_GeometryProgram = NULL;
	m_FragmentProgramFilename = fpFileName;
	m_VertexProgramFilename = vpFilename;
	m_GeometryProgramFilename = gpFileName;
	m_VertexProgramEntry = vpEntryPoint;
	m_FragmentProgramEntry = fpEntryPoint;
	m_GeometryProgramEntry = gpEntryPont;

	SetProgramFiles(m_VertexProgramFilename, m_FragmentProgramFilename, m_GeometryProgramFilename);
	SetProgramEntries(m_VertexProgramEntry, m_FragmentProgramEntry, m_GeometryProgramEntry);
	InitPrograms();
}

CgProgram::~CgProgram(void)
{
	cgDestroyProgram(*m_VertexProgram);
	cgDestroyProgram(*m_FragmentProgram);
	cgDestroyProgram(*m_GeometryProgram);
	cgDestroyContext(m_Context);
}

void CgProgram::InitPrograms()
{
	m_Context = cgCreateContext();
	m_VertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
	cgGLSetOptimalOptions(m_VertexProfile);
	m_FragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
	cgGLSetOptimalOptions(m_FragmentProfile);
	m_GeometryProfile = cgGLGetLatestProfile(CG_GL_GEOMETRY);
	cgGLSetOptimalOptions(m_GeometryProfile);

	if (m_VertexProgramFilename)
	{
		m_VertexProgram = new CGprogram;
		*m_VertexProgram = cgCreateProgramFromFile(m_Context, CG_SOURCE, m_VertexProgramFilename, m_VertexProfile, m_VertexProgramEntry, 0);
		cgGLLoadProgram(*m_VertexProgram);
		qDebug() <<"Building CgProgram: "<< m_VertexProgramFilename <<" "<< m_VertexProgramEntry << "\n";
		if(*m_VertexProgram==0)
		{
			qDebug() <<"!!!!CG_ERROR: Unable to build program: "<< m_VertexProgramFilename <<" "<< m_VertexProgramEntry << "\n";
			qDebug() << cgGetLastListing(m_Context) << "\n";
		}
	}

	if(m_FragmentProgramFilename)
	{
		m_FragmentProgram=new CGprogram;

		const char** arg;
		arg=new const char*[3];
		arg[0]="-ifcvt";
		arg[1]="all";
		arg[2]=NULL;

		*m_FragmentProgram=cgCreateProgramFromFile(m_Context,CG_SOURCE,m_FragmentProgramFilename,m_FragmentProfile,m_FragmentProgramEntry,arg);
		cgGLLoadProgram(*m_FragmentProgram);
		qDebug() <<"Building CgProgram: "<< m_FragmentProgramFilename <<" "<< m_FragmentProgramEntry << "\n";
		if(*m_FragmentProgram==0)
		{
			qDebug() <<"!!!!CG_ERROR: Unable to build program: "<< m_FragmentProgramFilename <<" "<< m_FragmentProgramEntry << "\n";
			qDebug() << cgGetLastListing(m_Context) << "\n";
		}
	}

	if(m_GeometryProgramFilename)
	{
		m_GeometryProgram = new CGprogram;
		*m_GeometryProgram = cgCreateProgramFromFile(m_Context,CG_SOURCE,m_GeometryProgramFilename,
			m_GeometryProfile, m_GeometryProgramEntry, 0);
		cgGLLoadProgram(*m_GeometryProgram);
		qDebug() <<"Building CgProgram: "<< m_GeometryProgramFilename <<" "<< m_GeometryProgramEntry << "\n";
		if(*m_GeometryProgram==0)
		{
			qDebug() <<"!!!!CG_ERROR: Unable to build program: "<< m_GeometryProgramFilename <<" "<< m_GeometryProgramEntry << "\n";
			qDebug() << cgGetLastListing(m_Context) << "\n";
		}
	}

	cgGLSetManageTextureParameters(m_Context,true);
}

void CgProgram::Enable()
{
	if (m_FragmentProgram)
	{
		cgGLEnableProfile(m_FragmentProfile);
		cgGLBindProgram(*m_FragmentProgram);
	}
	if (m_VertexProgram)
	{
		cgGLEnableProfile(m_VertexProfile);
		cgGLBindProgram(*m_VertexProgram);
	}
	if (m_GeometryProgram)
	{
		cgGLEnableProfile(m_GeometryProfile);
		cgGLBindProgram(*m_GeometryProgram);
	}
}

void CgProgram::Disable()
{
	if(m_FragmentProgram)
	{
		cgGLDisableProfile(m_FragmentProfile);
	}
	if(m_VertexProgram)
	{
		cgGLDisableProfile(m_VertexProfile);
	}
	if(m_GeometryProgram)
	{
		cgGLDisableProfile(m_GeometryProfile);
	}
}